#pragma once

// 2023.12.15 modify by haibo
#include <iostream>
#include <string>
#include <map>
#include <vector>
#include <memory>
#include <chrono>
#include <thread>
#include <mutex>
#include <fstream>
#include <nlohmann/json.hpp>

using json = nlohmann::json;
using ordered_json = nlohmann::ordered_json; // 显式使用有序JSON类型

// Data structures
struct Position {
    double x;
    double y;
    double theta;
    std::string mapId;
    std::string mapDescription;
};

struct NodePosition {
    Position position;
    double allowedDeviationXY;
    double allowedDeviationTheta;
};

struct AgvPosition {
    Position position;
    bool positionInitialized;
    double localizationScore;
    double deviationRange;
};

struct NodeState {
    std::string nodeId;
    std::string sequenceId;
    bool released;
    NodePosition nodePosition;
};

struct EdgeState {
    std::string edgeId;
    std::string sequenceId;
    bool released;
};

struct ActionState {
    std::string actionId;
    std::string actionType;
    std::string actionStatus;
    std::string actionDescription;
    std::string resultDescription;
};

struct Load {
    std::string loadId;
    std::string loadType;
    std::string loadPosition;
    std::map<std::string, double> boundingBoxReference;
    std::map<std::string, double> loadDimensions;
    double weight;
};

struct BatteryState {
    double batteryCharge;
    double batteryVoltage;
    int8_t batteryHealth;
    uint32_t reach;
    bool charging;
    bool chargeFinished;
};

struct PC_Switch {
    bool pc_pub_switch;
    bool map_pub_switch;
};

struct ErrorReferences {
    std::string referenceKey;
    std::string referenceValue;
};

struct Errors {
    std::string errorType;
    std::vector<ErrorReferences> errorReferences;
    std::string errorDescription;
    std::string errorLevel;
};

struct Events {
    int occur_id;
    std::string event_details;
};

struct State {
    int headerId;
    std::string orderId;
    int orderUpdateId;
    std::string timestamp;
    std::string version;
    std::string serialNumber;
    std::string manufacturer;
    std::string lastNodeId;
    std::string lastNodeSequenceId;
    bool driving;
    std::string operatingMode;
    BatteryState batteryStates;
    std::map<std::string, double> velocity;
    AgvPosition agvPosition;
    std::vector<NodeState> nodeStates;
    std::vector<EdgeState> edgeStates;
    std::vector<ActionState> actionStates;
    bool paused;
    double distanceSinceLastNode;
    std::vector<Errors> errors;
    std::string zoneSetId;
    bool newBaseRequest;
    std::vector<Load> loads;
    // std::map<std::string, std::variant<int, std::string>> agvEvents;
    double center_mileage;
    double online_time;
    double move_time;
    double fault_time;
    int order_counts;
    double discharge_time;
    int charge_counts;
    double charge_time;
};
// Data structures

inline void to_json(ordered_json& j, const AgvPosition& pos) {
	j = ordered_json{
		{"x", pos.position.x},
		{"y", pos.position.y},
		{"theta", pos.position.theta},
		{"mapId", pos.position.mapId},
		{"mapDescription", pos.position.mapDescription},
		{"positionInitialized", pos.positionInitialized},
		{"localizationScore", pos.localizationScore},
		{"deviationRange", pos.deviationRange}
	};
}

inline void to_json(ordered_json& j, const BatteryState& bat)
 {
	j = ordered_json{
		{"batteryCharge", bat.batteryCharge},
		{"batteryVoltage", bat.batteryVoltage},
		{"batteryHealth", bat.batteryHealth},
		{"reach", bat.reach},
		{"charging", bat.charging},
		{"chargeFinished", bat.chargeFinished}
	};
}

inline void to_json(ordered_json& j, const ActionState& state)
 {
	j = ordered_json{
		{"actionId", state.actionId},
		{"actionType", state.actionType},
		{"actionStatus", state.actionStatus},
		{"actionDescription", state.actionDescription},
		{"resultDescription", state.resultDescription}
	};
}

inline void to_json(ordered_json& j, const EdgeState& state)
 {
	j = ordered_json{
		{"edgeId", state.edgeId},
		{"sequenceId", state.sequenceId},
		{"released", state.released}
	};
}

inline void to_json(ordered_json& j, const Errors& erros)
 {
	j = ordered_json{
		{"errorType", erros.errorType},
		// {"errorReferences", erros.errorReferences},
		{"errorDescription", erros.errorDescription},
        {"errorType", erros.errorType},
		{"errorLevel", erros.errorLevel},
	};
}

inline void to_json(ordered_json& j, const Load& load)
 {
	j = ordered_json{
		{"loadId", load.loadId},
		{"loadType", load.loadType},
		{"boundingBoxReference", load.boundingBoxReference},
        {"loadDimensions", load.loadDimensions},
		{"weight", load.weight}
	};
}